package com.cmit.upay.monitor.service.impl;

import com.cmit.upay.monitor.util.DateUtils;
import com.cmit.upay.monitor.util.JsonUtil;
import com.cmit.upay.monitor.vo.QueueVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVPrinter;
import org.apache.commons.csv.QuoteMode;

import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;

/**
 * 写数据到csv文件<br/>
 *
 * @author liyuanchang
 * @version V1.0
 * @email liyuanchang@chinamobile.com
 * @date 2020-03-12 11:36
 */
@Slf4j
public class WriteDataToCsvService extends AbstractWriteDataToFileService {
    private CSVPrinter printer;

    public WriteDataToCsvService(String dir, int pageSize) {
        super(dir, pageSize);
    }

    @Override
    public void write(QueueVO data) {
        try {
            this.printer.printRecord(objToMap(data).values());
            if (log.isDebugEnabled()) {
                log.debug("写入数据{}完成", data);
            }
        } catch (IOException e) {
            log.error("写入数据{}出错{}", data, e.getMessage());
        }
    }

    @Override
    public void createNewFile() {
        this.filename = DateUtils.get_yyyyMMddhhmmss();
        this.filename += ".csv";
        try {
            // 如果需要，创建目录
            Files.createDirectories(Paths.get(dir));
            Path path = Paths.get(dir).resolve(this.filename);
            closePrinterIfNecessary();
            // 创建新文件
            FileWriter fileWriter = new FileWriter(path.toAbsolutePath().toString());
            CSVFormat format = CSVFormat.RFC4180;
            format = format.withHeader(getHeaders()).withQuoteMode(QuoteMode.ALL).withIgnoreHeaderCase().withTrim();
            this.printer = new CSVPrinter(fileWriter, format);
            // 计数重置
            resetFileLines();
            log.info("创建新文件{}完成", this.filename);
        } catch (Exception e) {
            String errorMsg = String.format("创新新文件{}过程出错", this.filename);
            log.error(errorMsg);
            throw new RuntimeException(errorMsg, e);
        }
    }

    @Override
    public void flushData() {
        try {
            this.printer.flush();
        } catch (IOException e) {
            log.warn("刷新数据出错" + e.getMessage());
        }
    }

    private String[] getHeaders() {
        QueueVO vo = QueueVO.builder().build();
        Map<String, String> map = objToMap(vo);
        String[] headers = new String[map.keySet().size()];
        headers = map.keySet().toArray(headers);
        return headers;
    }

    private Map<String, String> objToMap(QueueVO vo) {
        String json = JsonUtil.object2JsonStr(vo);
        Map<String, String> map = JsonUtil.jsonStr2Obj(json, HashMap.class);
        return map;
    }

    private void closePrinterIfNecessary() {
        if (this.printer != null) {
            try {
                this.printer.close();
            } catch (IOException e) {
                printer = null;
            }
        }
    }
}
